use std::net::SocketAddr;
use axum::{
    http::StatusCode, response::Html, routing::{get, post}, Json, Router,
};
use serde::{Serialize, Deserialize};
use tokio;
// jsonwebtoken 是一种用于双方之间安全传输信息的紧凑、自包含的方式。它特别适用于在各方之间通过 HTTPS 协议安全地传输信息。
// JWT 的核心思想是通过数字签名来验证信息的完整性以及确保信息是由指定的发送者发送的。
use jsonwebtoken as jwt;




const SECRET_KEY: &[u8] = b"lalala"; //密钥

#[derive(Debug, Serialize, Deserialize)]
pub struct Todo{
    pub id: usize,
    pub title: String, //标题
    pub completed: bool, //是否完成
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CreateTodo {
    pub title: String, //标题
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
    pub id: usize,
    pub name: String,
    pub exp: usize, //令牌的过期时间
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LoginRequest {
    email: String,
    password: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LoginResponse {
    token: String,
}

#[tokio::main]
async fn main() {

    let app = Router::<()>::new()
        .route("/", get(index_handler))
        .route("/todos", get(todo_handler).post(create_todo_handler)) //todos 路径配置了 GET 和 POST 请求处理器
        .route("/login", post(login_handler)); //登录路径配置了POST请求处理器
    let addr = SocketAddr::from(([127, 0, 0, 1], 8080));
    println!("Listening on http://{}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); //创建监听器
    axum::serve(listener, app).await.unwrap();  //启动服务
}

async fn index_handler() -> Html<&'static str> {
    Html("<h1>Hello, world!</h1>")
}

async fn todo_handler() -> Json<Vec<Todo>> {
    Json(vec![
        Todo {
            id: 1,
            title: String::from("Todo 1"),
            completed: true,
        },
        Todo {
            id: 2,
            title: String::from("Todo 2"),
            completed: false,
        },
    ])
}
//eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwibmFtZSI6InVzZXIiLCJleHAiOjE3MzUxOTE2NzZ9.1J1_e7T7nGMrhas1yiIF5-EbreuMOCFSxVTcKINmtxw
// Axum框架能够自动从HTTP请求的body中解析JSON数据，并将其转换为Rust中的结构体实例
// Json<CreateTodo>类型表示Axum期望从请求的body中解析出CreateTodo结构体的实例。
async fn create_todo_handler(Json(todo): Json<CreateTodo>) -> StatusCode {
    println!("create todo: {:?}", todo);
    //create todo: CreateTodo { title: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwibmFtZSI6InVzZXIiLCJleHAiOjE3MzUxOTE2NzZ9.1J1_e7T7nGMrhas1yiIF5-EbreuMOCFSxVTcKINmtxw" }
    StatusCode::CREATED
}



//一个测试函数，根据用户email和password获取用户信息
async fn login_handler(Json(login): Json<LoginRequest>) -> Json<LoginResponse> {
    println!("login: {:?}", login);
    //跳过登录信息验证
    let user = Claims {
        id: 1,
        name: String::from("user"),
        exp: get_epoch() + 14 * 24 * 60 * 60,
    }; 

    //from_secret 将秘密转换为一个 EncodingKey 实例，该实例可以用于签名 JWT。
    let key = jwt::EncodingKey::from_secret(SECRET_KEY);
    //jwt::encode函数是用于生成JWT令牌 - JWT令牌由三部分组成，即标头、有效载荷和签名。
    //是将头部信息、负载信息和密钥组合起来，使用指定的算法生成一个JWT令牌。这个令牌是一个经过签名的JSON字符串，它可以在客户端和服务器之间安全地传输用户身份信息和其他敏感数据。
    let token = jwt::encode(&jwt::Header::default(), &user, &key).unwrap();
    println!("token: {}", token);
    Json(LoginResponse { token })
}

fn get_epoch() -> usize {
    std::time::SystemTime::now() //获取当前时间戳
        .duration_since(std::time::UNIX_EPOCH) //计算从 UNIX 纪元到当前系统时间的时间差
        .unwrap()
        .as_secs() as usize
}


//1. login 获取用户信息